package skeleton;

import java.io.IOException;
import java.util.Random;

import javax.microedition.lcdui.*;
import javax.microedition.lcdui.game.*;

import util.*;

public class ColorfulEgg extends GameCanvas implements Runnable {
	static Thread uniqueIns = null;
	static boolean isRun = false;
	static int count = 0;
	static final int CHOOSE = 0;
	static final int BREAK = 1;
	static final int NEW_BG = 2;
	static final int SHOW_RES = 3;
	Image sitTiger, bg, fireImg, breakBg, goldImg, badImg, silverImg;
	Image[] bigEgg;
	Pair sitTigerPos, bgPos, pointerPos;
	Pair fireOffset, goldOffset, badOffset, silverOffset;
	Pair[] eggPos;
	int gw, gh, chose, state, result;
	Sprite[] eggSprite;
	Sprite fireSprite;
	LayerManager lm;
	Random rand;

	public ColorfulEgg() {
		super(false);
		loadResource();
		initialParameter();
		start();
	}
	
	private void initialParameter() {
		this.setFullScreenMode(true);
		gw = getWidth();
		gh = getHeight();
		sitTigerPos = new Pair(gw-sitTiger.width, gh-sitTiger.height);
		bgPos = new Pair(0, 0);
		eggPos = new Pair[3];
		eggPos[0] = new Pair(200, 50);
		eggPos[1] = new Pair(100, 250);
		eggPos[2] = new Pair(300, 250);
		lm = new LayerManager();

		Sprite animate;
		animate = new Sprite(sitTiger);
		animate.setPosition(sitTigerPos.first, sitTigerPos.second);
		lm.append(animate);
		
		eggSprite = new Sprite[3];
		int[] seq = {0,1,2,1};
		for (int i=0; i<3; ++i) {
			animate = new Sprite(bigEgg[i], bigEgg[i].width/3, bigEgg[i].height);
			animate.setFrameSequence(seq);
			eggSprite[i] = animate;
			animate.setPosition(eggPos[i].first, eggPos[i].second);
			lm.append(animate);
		}
		
		fireOffset = getOffsetToEgg(fireImg.width/2, fireImg.height);

		fireSprite = new Sprite(fireImg, fireImg.width/2, fireImg.height);
		fireSprite.setVisible(false);
//		lm.insert(fireSprite, 0);
		lm.append(fireSprite);

		goldOffset = getOffsetToEgg(goldImg.width, goldImg.height);
		silverOffset = getOffsetToEgg(silverImg.width, silverImg.height);
		badOffset = getOffsetToEgg(badImg.width, badImg.height);
		
		chose = 0;
		state = CHOOSE;
		rand = new Random();
	}

	private Pair getOffsetToEgg(int width, int height) {
		return new Pair(-(width - bigEgg[0].width/3)/2,
				-(height - bigEgg[0].height)/2);
	}

	private void loadResource() {
		try {
			sitTiger = Image.createImage("/resource/tiger.png");
			bg = Image.createImage("/resource/bg2.jpg");
			breakBg = Image.createImage("/resource/bg.jpg");
			bigEgg = new Image[3];
			bigEgg[0] = Image.createImage("/resource/egg0.png");
			bigEgg[1] = Image.createImage("/resource/egg1.png");
			bigEgg[2] = Image.createImage("/resource/egg2.png");
			fireImg = Image.createImage("/resource/fire.png"); 
			goldImg = Image.createImage("/resource/gold.png");
			badImg = Image.createImage("/resource/badegg.png");
			silverImg = Image.createImage("/resource/silver.png");
		} catch (IOException e) {
			Lib.assertNotReached("load resource failed.");
			e.printStackTrace();
		}
	}
	
	synchronized void start() {
		if (uniqueIns == null) {
			uniqueIns = new Thread(this);
			uniqueIns.start();
		}
		else
			System.err.println("already run an instance!!!");
	}
	
	public void run() {
		if (uniqueIns == null)
			Lib.assertNotReached();
		int interval = 200;
		long lastTime = System.currentTimeMillis();
		Thread t = Thread.currentThread();
		while (t == uniqueIns) {
			if (System.currentTimeMillis() - lastTime > interval) {
				lastTime = System.currentTimeMillis();
				doRepaint();
				try {
					Thread.sleep(interval);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				++count;
			}
		}
	}
	
	private void doRepaint() {
		repaint();
		serviceRepaints();
	}
	
	public void paint(Graphics g) {
		doPaint(g);
	}
	
	public void doPaint(Graphics g) {
		//before paint
		switch (state) {
		case CHOOSE:
			g.drawImage(bg, bgPos.first, bgPos.second, 0);
			for (int i=0; i<3; ++i)
				if (i != chose)
					eggSprite[i].setFrame(0);
				else
					eggSprite[chose].nextFrame();
			break;
		case BREAK:
			g.drawImage(bg, bgPos.first, bgPos.second, 0);
			break;
		case NEW_BG:
			g.drawImage(breakBg, bgPos.first, bgPos.second, 0);
			break;
		case SHOW_RES:
			int interval = 500;
			try {
					Thread.sleep(interval);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			showRes(g);
			break;
		default:
			Lib.assertNotReached("undefined state.");
		}
		
		g.setColor(0xFFFFFF);
		g.drawString("do paint " + count + " times.", 0, 0, 0);
		for (int i=0; i<lm.getSize(); ++i)
			lm.getLayerAt(i).paint(g);
		
		//after paint
		switch (state) {
		case CHOOSE:
		case SHOW_RES:
			break;
		case NEW_BG:
			state = SHOW_RES;
			break;
		case BREAK:
			fireSprite.nextFrame();
			if (fireSprite.getFrame() == 0) {
				state = NEW_BG;
				fireSprite.setVisible(false);
			}
			break;
		default:
			Lib.assertNotReached("undefined state.");
		}
	}
	
	private void showRes(Graphics g) {
		switch (result) {
		case 0://gold
			g.drawImage(goldImg, eggPos[chose].first + goldOffset.first,
					eggPos[chose].second + goldOffset.second, 0);
			break;
		case 1://silver
			g.drawImage(silverImg, eggPos[chose].first + silverOffset.first,
					eggPos[chose].second + silverOffset.second, 0);
			break;
		case 2://copper
			g.drawImage(badImg, eggPos[chose].first + badOffset.first,
					eggPos[chose].second + badOffset.second, 0);
			break;
		default:
			Lib.assertNotReached();
		}
	}

	protected void keyPressed(int keycode) {
		int theKey = getGameAction(keycode);
		switch (theKey) {
		case DOWN:
			if (state != CHOOSE) break;
			if (chose == 0 || chose == 2)
				chose = 1;
			else
				chose = 2;
			break;
		case LEFT:
			if (state != CHOOSE) break;
			chose = 1;
			break;
		case RIGHT:
			if (state != CHOOSE) break;
			chose = 2;
			break;
		case UP:
			if (state != CHOOSE) break;
			chose = 0;
			break;
		case FIRE:
			if (state == CHOOSE) hit();
			else if (state == SHOW_RES) {
				for (int i=0; i<lm.getSize(); ++i)
					lm.getLayerAt(i).setVisible(true);
				fireSprite.setVisible(false);
				state = CHOOSE;
			}
			break;
		default:
			Lib.assertNotReached("undefined operation.");
		}
	}
	
	private void hit() {
		state = BREAK;
		for (int i=0; i<lm.getSize(); ++i)
			lm.getLayerAt(i).setVisible(false);
		fireSprite.setVisible(true);
		fireSprite.setPosition(eggPos[chose].first + fireOffset.first,
				eggPos[chose].second + fireOffset.second);
		calResult();
	}
	
	private void calResult() {
		result = rand.nextInt(3);
	}
}
